1 module d_tree_sitter.tree_cursor; 2 3 extern (C): 4 5 import d_tree_sitter.node; 6 7 import std.exception : enforce; 8 import std..string : fromStringz; 9 10 /// A stateful object for walking a syntax `Tree` efficiently. 11 struct TreeCursor 12 { 13 import d_tree_sitter.libc : TSTreeCursor, ts_tree_cursor_copy, 14 ts_tree_cursor_current_node, ts_tree_cursor_current_field_id, 15 ts_tree_cursor_current_field_name, ts_tree_cursor_goto_first_child, 16 ts_tree_cursor_goto_parent, 17 ts_tree_cursor_goto_next_sibling, ts_tree_cursor_goto_first_child_for_byte, 18 ts_tree_cursor_reset, ts_tree_cursor_delete; 19 20 /** internal `TSTreeCursor` */ 21 TSTreeCursor tstreecursor; 22 23 /** Create a new tree cursor */ 24 this(TSTreeCursor tstreecursor) @nogc nothrow 25 { 26 this.tstreecursor = tstreecursor; 27 } 28 29 ~this() @nogc nothrow 30 { 31 return ts_tree_cursor_delete(&tstreecursor); 32 } 33 34 /** Copy a tree cursor */ 35 this(ref return scope TreeCursor otherTreeCursor) @nogc nothrow 36 { 37 this.tstreecursor = ts_tree_cursor_copy(&otherTreeCursor.tstreecursor); 38 } 39 40 /** Copy a tree cursor */ 41 this(TreeCursor* otherTreeCursor) @nogc nothrow 42 { 43 this.tstreecursor = ts_tree_cursor_copy(&otherTreeCursor.tstreecursor); 44 } 45 46 @disable this(this); // disable postblit 47 48 /** Get the tree cursor's current [Node]. */ 49 auto node() const @nogc nothrow 50 { 51 return Node(ts_tree_cursor_current_node(&tstreecursor)); 52 } 53 54 /** 55 Get the numerical field id of this tree cursor's current node. 56 57 See also [field_name](TreeCursor::field_name). 58 */ 59 auto field_id() const @nogc 60 { 61 auto id = ts_tree_cursor_current_field_id(&tstreecursor); 62 assert(id != 0, "id is 0."); 63 return id; 64 } 65 66 /** Get the field name of this tree cursor's current node. */ 67 auto field_name() const @nogc nothrow 68 { 69 return fromStringz(ts_tree_cursor_current_field_name(&tstreecursor)); 70 } 71 72 /** 73 Move this cursor to the first child of its current node. 74 75 This returns `true` if the cursor successfully moved, and returns `false` 76 if there were no children. 77 */ 78 auto goto_first_child() @nogc nothrow 79 { 80 return ts_tree_cursor_goto_first_child(&tstreecursor); 81 } 82 83 /** 84 Move this cursor to the parent of its current node. 85 86 This returns `true` if the cursor successfully moved, and returns `false` 87 if there was no parent node (the cursor was already on the root node). 88 */ 89 auto goto_parent() @nogc nothrow 90 { 91 return ts_tree_cursor_goto_parent(&tstreecursor); 92 } 93 94 /** 95 Move this cursor to the next sibling of its current node. 96 97 This returns `true` if the cursor successfully moved, and returns `false` 98 if there was no next sibling node. 99 */ 100 auto goto_next_sibling() @nogc nothrow 101 { 102 return ts_tree_cursor_goto_next_sibling(&tstreecursor); 103 } 104 105 /** 106 Move this cursor to the first child of its current node that extends beyond 107 the given byte offset. 108 109 This returns the index of the child node if one was found, and returns `None` 110 if no such child was found. 111 */ 112 auto goto_first_child_for_byte(size_t index) 113 { 114 auto result = ts_tree_cursor_goto_first_child_for_byte(&tstreecursor, cast(uint) index); 115 enforce(result >= 0, "result is less than 0."); 116 return result; 117 } 118 119 /** Re-initialize this tree cursor to start at a different node. */ 120 auto reset(Node node) @nogc nothrow 121 { 122 return ts_tree_cursor_reset(&tstreecursor, node.tsnode); 123 } 124 }